package com.aotain.oframework.util.io;

import java.io.File;
import java.io.FilenameFilter;
import java.util.StringTokenizer;
import java.util.Vector;

/**
 * @author Jacob.cw.Zhang@gmail.com
 */
public class WildCardFilter implements FilenameFilter {
	
	private String wildPattern = null;
	private Vector<String> pattern = new Vector<String>();
	static final String FIND = "find";
	static final String EXPECT = "expect";
	static final String ANYTHING = "anything";
	static final String NOTHING = "nothing";
	
	public WildCardFilter(String wildString){
		wildPattern = wildString;
		wildString = wildString.toLowerCase();
		int i = wildString.indexOf("**");
		while (i > 0) {
			wildString = wildString.substring(0, i + 1) + wildString.substring(i + 2);
			i = wildString.indexOf("**");
		}
		StringTokenizer tokens = new StringTokenizer(wildString, "*", true);
		String token = null;
		while (tokens.hasMoreTokens()) {
			token = tokens.nextToken();
			if (token.equals("*")) {
				pattern.add(FIND);
				if (tokens.hasMoreTokens()) {
					token = tokens.nextToken();
					pattern.addElement(token);
				} else {
					pattern.addElement(ANYTHING);
				}
			} else {
				pattern.addElement(EXPECT);
				pattern.addElement(token);
			}
		}
		if (!"*".equals(token)) {
			pattern.addElement(EXPECT);
			pattern.addElement(NOTHING);
		}
	}

	public boolean accept(File dir, String name) {
		/**
		 * allow directories to match all patterns not sure if this is the best
		 * idea, but suits my needs for now
		 */
		String path = dir.getPath();
		if (!"/".endsWith(path) && !"\\".endsWith(path)) {
			path += File.separator;
		}
		File tempFile = new File(path, name);
		if (tempFile.isDirectory()) {
			return true;
		}
		name = name.toLowerCase();
		boolean acceptName = true;
		String command = null;
		String param = null;
		int currPos = 0;
		int cmdPos = 0;
		while (currPos < pattern.size()) {
			command = pattern.elementAt(cmdPos);
			param = pattern.elementAt(cmdPos + 1);
			if (command.equals(FIND)) {
				if (param.equals(ANYTHING)) {
					break;
				}
				int nextPos = name.indexOf(param, currPos);
				if (nextPos >= 0) {
					currPos = nextPos + param.length();
				} else {
					acceptName = false;
					break;
				}
			} else {
				if (command.equals(EXPECT)) {
					if (param.equals(NOTHING)) {
						if (currPos != name.length()) {
							acceptName = false;
						}
						break;
					} else {
						int nextPos = name.indexOf(param, currPos);
						if (nextPos != currPos) {
							acceptName = false;
							break;
						} 		
						currPos += param.length();
					}
				}
			}
			cmdPos += 2;
		}
		return acceptName;
	}
	
	@Override
	public String toString() {
		return wildPattern;
	}
	
	public String toPattern() {
		StringBuffer out = new StringBuffer();
		int i = 0;
		while (i < pattern.size()) {
			out.append("(");
			out.append((String) pattern.elementAt(i));
			out.append(" ");
			out.append((String) pattern.elementAt(i + 1));
			out.append(") ");
			i += 2;
		}
		return out.toString();
	}

}
